package fr.umlv.galcon.player.ai;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Timer;
import java.util.TreeMap;

import fr.umlv.galcon.item.ItemListSingleton;
import fr.umlv.galcon.planet.Planet;
import fr.umlv.galcon.player.Player;
import fr.umlv.galcon.ship.SendShip;

/**
 * Make an AI player attack planets.
 * 
 */
public class AIAttack implements AIStrategy {
    private final Player player;

    private final Random random;
    private final Map<Integer, Planet> bestProduction = new HashMap<Integer, Planet>();

    /**
     * Constructor
     * 
     * @param player
     *            The player concerned.
     */
    public AIAttack(Player player) {
	this.player = player;
	this.random = new Random();
    }

    /**
     * Attack a Planet.
     * 
     * @param planet
     *            The Planet which launch the attack.
     */
    private void attack(Planet planet) {
	Timer timer = new Timer();
	Planet target = selectTargetPlanet(planet);
	// Calculate the quantity of Ship to send
	if (target != null) {
	    int shipToSend = (int) ((this.random.nextInt(70) / 100f) * planet.getStock().getRealStock());
	    // Set the real stock of the Planet
	    planet.getStock().setRealStock(planet.getStock().getRealStock() - shipToSend);
	    // send ships
	    SendShip s = new SendShip(planet, target, shipToSend);
	    timer.schedule(s, 3000, 2000);
	}
    }

    @Override
    public void action() {
	Iterator<Planet> it = ItemListSingleton.getInstance().getPlanetList().iterator();
	Planet planet;

	// For each Planet
	while (it.hasNext()) {
	    planet = it.next();
	    // If it's a rival Planet
	    if (planet.getOwner().getId() == this.player.getId() && planet.getStock().getRealStock() > this.random.nextInt(20) + 10)
		attack(planet);
	}
    }

    /**
     * Function which select an planet to attack
     * 
     * @param planet
     *            the source planet
     * @return The Planet to attack.
     */
    private Planet selectTargetPlanet(Planet planet) {
	int action = this.random.nextInt(3);
	boolean canAttack = false;

	Map<Double, Planet> nearest = new HashMap<Double, Planet>();
	Map<Integer, Planet> weakest = new HashMap<Integer, Planet>();

	for (Planet p : ItemListSingleton.getInstance().getPlanetList()) {
	    if (p.getOwner().getId() != this.player.getId()) {
		double distance = planet.getCenter().distance(p.getCenter());
		nearest.put(distance, p);
		weakest.put(p.getStock().getShipStock(), p);
		bestProduction.put(p.getStock().getProductionRate(), p);
		canAttack = true;
	    }
	}

	if (!canAttack)
	    return null;

	switch (action) {
	case 0:
	    return new TreeMap<Double, Planet>(nearest).firstEntry().getValue();
	case 1:
	    return new TreeMap<Integer, Planet>(weakest).firstEntry().getValue();
	case 2:
	    return new TreeMap<Integer, Planet>(bestProduction).firstEntry().getValue();
	default:
	    return null;
	}
    }

}
